package com.zt.bigdata.practise.time;

import java.sql.Timestamp;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;
import java.util.Locale;
import java.util.stream.IntStream;

/**
 *
 */
public class Chapter8 {
    public static void main(String[] args) {
        //8.1 Date-Time API中的基本类
        System.out.println("Instant.now():" + Instant.now());
        System.out.println("LocalDate.now():" + LocalDate.now());
        System.out.println("LocalTime.now():" + LocalTime.now());
        System.out.println("LocalDateTime.now(): " + LocalDateTime.now());
        System.out.println("ZonedDateTime.now(): " + ZonedDateTime.now());

//        System.out.println("Instant.now():" + Instant.now().atOffset(ZoneOffset.ofHours(8)));
        //8.2 根据现有实例创建日期和时间

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate start = LocalDate.of(2017, Month.FEBRUARY, 2);
        LocalDate end = start.plusDays(3);
        assertEquals("2017-02-05", end.format(formatter));
        end = start.plusWeeks(5);
        assertEquals("2017-03-09", end.format(formatter));
        end = start.plusMonths(7);
        assertEquals("2017-09-02", end.format(formatter));
        end = start.plusYears(2);
        assertEquals("2019-05-02", end.format(formatter));

        System.out.println(DateTimeFormatter.ISO_LOCAL_DATE_TIME);

        LocalDateTime localDateTime = LocalDateTime.of(2017, Month.FEBRUARY, 2, 11, 30);
        LocalDateTime localDateTime1 = localDateTime.withMinute(45);
        assertEquals("2017-02-02T11:45:00",
                localDateTime1.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        localDateTime1 = localDateTime.withHour(16);
        assertEquals("2017-02-02T16:30:00",
                localDateTime1.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        localDateTime1 = localDateTime.withDayOfMonth(28);
        assertEquals("2017-02-28T11:30:00",
                localDateTime1.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        localDateTime1 = localDateTime.withDayOfYear(300);
        assertEquals("2017-10-27T11:30:00",
                localDateTime1.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        localDateTime1 = localDateTime.withYear(2020);
        assertEquals("2020-02-02T11:30:00", localDateTime1.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));


        //8.3 调节器与查询
        LocalDateTime a = LocalDateTime.of(2017, Month.FEBRUARY, 2, 11, 30);
        LocalDateTime b = a.with(TemporalAdjusters.firstDayOfNextMonth());
        assertEquals("2017-03-01T11:30", b.toString());
        b = a.with(TemporalAdjusters.next(DayOfWeek.THURSDAY));
        assertEquals("2017-02-09T11:30", b.toString());
        b = a.with(TemporalAdjusters.previousOrSame(DayOfWeek.THURSDAY));
        assertEquals("2017-02-02T11:30", b.toString());


        IntStream.rangeClosed(1, 14)
                .mapToObj(day -> LocalDate.of(2017, Month.JULY, day))
                .forEach(date ->
                        assertEquals(14, date.with(Chapter8::adjustInto).getDayOfMonth()));

        IntStream.rangeClosed(15, 31)
                .mapToObj(day -> LocalDate.of(2017, Month.JULY, day))
                .forEach(date ->
                        assertEquals(31,
                                date.with(Chapter8::adjustInto).getDayOfMonth()));


        //8.4 将java.util.Date转换为java.time.LocalDate
        new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

        //8.5 解析与格式化
        LocalDate date = LocalDate.now();
        System.out.println("Full : " +
                date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)));
        System.out.println("Long : " +
                date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG)));
        System.out.println("Medium : " +
                date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)));
        System.out.println("Short : " +
                date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)));
        System.out.println("France : " +
                date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)
                        .withLocale(Locale.FRANCE)));
        System.out.println("India : " +
                date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).withLocale(new Locale("hin", "IN"))));
        System.out.println("Brazil : " +
                date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)
                        .withLocale(new Locale("pt", "BR"))));
        System.out.println("Japan : " +
                date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)
                        .withLocale(Locale.JAPAN)));
        Locale loc = new Locale.Builder().setLanguage("sr")
                .setScript("Latn")
                .setRegion("RS")
                .build();
        System.out.println("Serbian: " +
                date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)
                        .withLocale(loc)));
        System.out.println("中国: " +
                date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)
                        .withLocale(Locale.TAIWAN)));

        ZonedDateTime moonLanding = ZonedDateTime.of(
                LocalDate.of(1969, Month.JULY, 20),
                LocalTime.of(20, 18),
                ZoneId.of("UTC")
        );
        System.out.println(moonLanding.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
        DateTimeFormatter dateTimeFormatter =
                DateTimeFormatter.ofPattern("uuuu/MMMM/dd hh:mm:ss a zzz GG");
        System.out.println(moonLanding.format(dateTimeFormatter));
        dateTimeFormatter = DateTimeFormatter.ofPattern("uuuu/MMMM/dd hh:mm:ss a VV xxxxx");
        System.out.println(moonLanding.format(dateTimeFormatter));


        LocalDateTime localDateTime2 = LocalDateTime.now();
        System.out.println(localDateTime2);
        System.out.println("localDateTime:" + Timestamp.valueOf(localDateTime2).getTime());
        System.out.println("localDateTime:" + localDateTime2.toInstant(ZoneOffset.of("+8")).toEpochMilli());
        System.out.println("localDateTime:" + System.currentTimeMillis());

    }

    private static void assertEquals(String left, String right) {
        if (left != null && left.equals(right)) {
            System.out.println(left + " is equals to " + right);
        } else {
            System.out.println(left + " is not equals to " + right);
        }
    }

    private static void assertEquals(int left, int right) {
        if (left == right) {
            System.out.println(left + " is equals to " + right);
        } else {
            System.out.println(left + " is not equals to " + right);
        }
    }

    private static Temporal adjustInto(Temporal input) {
        LocalDate date = LocalDate.from(input);
        int day;
        if (date.getDayOfMonth() < 15) {
            day = 15;
        } else {
            day = date.with(TemporalAdjusters.lastDayOfMonth())
                    .getDayOfMonth();
        }
        date = date.withDayOfMonth(day);
        if (date.getDayOfWeek() == DayOfWeek.SATURDAY ||
                date.getDayOfWeek() == DayOfWeek.SUNDAY) {
            date = date.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY));
        }
        return input.with(date);
    }

    public LocalDate convertFromSqlDatetoLD(java.sql.Date sqlDate) {
        return sqlDate.toLocalDate();
    }

    public java.sql.Date convertToSqlDateFromLD(LocalDate localDate) {
        return java.sql.Date.valueOf(localDate);
    }

    public LocalDateTime convertFromTimestampToLDT(Timestamp timestamp) {
        return timestamp.toLocalDateTime();
    }

    public Timestamp convertToTimestampFromLDT(LocalDateTime localDateTime) {
        return Timestamp.valueOf(localDateTime);
    }
}
